package com.jiangyao.common.utils;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

/**
 * 时间工具
 *
 * @author yangyongchuan
 */
public class DateUtil {
	private final static Logger logger = LoggerFactory.getLogger(DateUtil.class);

	private final static long day_ms = 24 * 60 * 60 * 1000;
	private final static long hour_ms = 60 * 60 * 1000;
	/**
	 * yyyy-MM-dd hh:mm:ss
	 */
	public final static SimpleDateFormat DF_SIMPLE_12 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public final static SimpleDateFormat DF_SIMPLE_24 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 * yyyy-MM-dd hh:mm
	 */
	public final static SimpleDateFormat DF_YMDHM_12 = new SimpleDateFormat("yyyy-MM-dd hh:mm");
	/**
	 * yyyy-MM-dd HH:mm
	 */
	public final static SimpleDateFormat DF_YMDHM_24 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
	/**
	 * yyyy.MM.dd HH:mm
	 */
	public final static SimpleDateFormat DF_YMDHM_24_2 = new SimpleDateFormat("yyyy.MM.dd HH:mm");
	/**
	 * yyyy.MM.dd
	 */
	public final static SimpleDateFormat DF_YMD_24 = new SimpleDateFormat("yyyy.MM.dd");
	/**
	 * MM.dd HH:mm
	 */
	public final static SimpleDateFormat DF_MDHM_24 = new SimpleDateFormat("MM.dd HH:mm");
	/**
	 * MM.dd
	 */
	public final static SimpleDateFormat DF_MD_24 = new SimpleDateFormat("MM.dd");
	/**
	 * yyyy-MM
	 */
	public final static SimpleDateFormat DF_YM = new SimpleDateFormat("yyyy-MM");
	/**
	 * yyyy-MM-dd
	 */
	public final static SimpleDateFormat DF_YMD = new SimpleDateFormat("yyyy-MM-dd");
	/**
	 * yyyy/MM/dd
	 */
	public final static SimpleDateFormat DF_YMD_3 = new SimpleDateFormat("yyyy/MM/dd");
	/**
	 * yyyy.MM.dd
	 */
	public final static SimpleDateFormat DF_YMD_4 = new SimpleDateFormat("yyyy.MM.dd");
	/**
	 * yyyyMMdd
	 */
	public final static SimpleDateFormat DF_YMD_2 = new SimpleDateFormat("yyyyMMdd");
	/**
	 * hh:mm:ss
	 */
	public final static SimpleDateFormat DF_HMS_12 = new SimpleDateFormat("hh:mm:ss");
	/**
	 * HH:mm:ss
	 */
	public final static SimpleDateFormat DF_HMS_24 = new SimpleDateFormat("HH:mm:ss");
	/**
	 * yyyy年MM月dd日
	 */
	public final static SimpleDateFormat DF_SIMPLE = new SimpleDateFormat("yyyy年MM月dd日");
	/**
	 * yyyy年MM月d日
	 */
	public final static SimpleDateFormat DF_SIMPLE_DAY = new SimpleDateFormat("yyyy年MM月d日");
	/**
	 * yyyy年MM月dd日H时mm分ss秒
	 */
	public final static SimpleDateFormat DF_SIMPLE_ZH = new SimpleDateFormat("yyyy年MM月dd日H时mm分ss秒");
	/**
	 * yyyy年MM月dd日 HH:mm
	 */
	public final static SimpleDateFormat DF_SIMPLE_ZH_2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
	/**
	 * MM月dd日
	 */
	public final static SimpleDateFormat DF_YM_ZH = new SimpleDateFormat("MM月dd日");
	/**
	 * yyyyMMddHHmmssSSS
	 */
	public final static SimpleDateFormat DF_FULL = new SimpleDateFormat("yyyyMMddHHmmssSSS");
	/**
	 * yyyyMMddHHmmss
	 */
	public final static SimpleDateFormat DF_FULL2 = new SimpleDateFormat("yyyyMMddHHmmss");
	/**
	 * H时mm分
	 */
	public final static SimpleDateFormat DF_HHMM_ZH = new SimpleDateFormat("H时mm分");
	/**
	 * MM月dd日H时mm分
	 */
	public final static SimpleDateFormat DF_MMDDHHMM_ZH = new SimpleDateFormat("M月d日H时mm分");
	/**
	 * MM-dd HH:mm
	 */
	public final static SimpleDateFormat DF_MMDDHHMM = new SimpleDateFormat("MM-dd HH:mm");
	/**
	 * yyyy/MM/dd
	 */
	public final static SimpleDateFormat DF_MDY = new SimpleDateFormat("MM/dd/yyyy");

	/**
	 * yyyy/MM/dd HH:mm:ss
	 */
	public final static SimpleDateFormat DF_MDYHDS = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

	/**
	 * yyyy-MM-dd hh:mm:ss
	 */
	public final static SimpleDateFormat DF_SIMPLE_12_GMT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	/**
	 * yyyy-MM-dd HH:mm:ss
	 */
	public final static SimpleDateFormat DF_SIMPLE_24_GMT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 * yyyy-MM-dd hh:mm
	 */
	public final static SimpleDateFormat DF_YMDHM_12_GMT = new SimpleDateFormat("yyyy-MM-dd hh:mm");
	/**
	 * yyyy-MM-dd HH:mm
	 */
	public final static SimpleDateFormat DF_YMDHM_24_GMT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
	/**
	 * yyyy-MM-dd
	 */
	public final static SimpleDateFormat DF_YMD_GMT = new SimpleDateFormat("yyyy-MM-dd");
	/**
	 * yyyyMM
	 */
	public final static SimpleDateFormat DF_YM_2_GMT = new SimpleDateFormat("yyyyMM");
	/**
	 * yyyyMMdd
	 */
	public final static SimpleDateFormat DF_YMD_2_GMT = new SimpleDateFormat("yyyyMMdd");
	/**
	 * hh:mm:ss
	 */
	public final static SimpleDateFormat DF_HMS_12_GMT = new SimpleDateFormat("hh:mm:ss");
	/**
	 * HH:mm:ss
	 */
	public final static SimpleDateFormat DF_HMS_24_GMT = new SimpleDateFormat("HH:mm:ss");
	/**
	 * HH:mm
	 */
	public final static SimpleDateFormat DF_HM_24_GMT = new SimpleDateFormat("HH:mm");
	/**
	 * yyyy年MM月dd日H时mm分ss秒
	 */
	public final static SimpleDateFormat DF_SIMPLE_ZH_GMT = new SimpleDateFormat("yyyy年MM月dd日H时mm分ss秒");
	/**
	 * yyyy年MM月dd日 HH:mm
	 */
	public final static SimpleDateFormat DF_SIMPLE_ZH_2_GMT = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
	/**
	 * yyyyMMddHHmmssSSS
	 */
	public final static SimpleDateFormat DF_FULL_GMT = new SimpleDateFormat("yyyyMMddHHmmssSSS");

	static {
		DF_SIMPLE_12_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_SIMPLE_24_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_YMDHM_12_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_YMDHM_24_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_YMD_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_YMD_2_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_HMS_12_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_HMS_24_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_SIMPLE_ZH_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_SIMPLE_ZH_2_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
		DF_FULL_GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
	}

	/**
	 * 时间字符串转化成 Date
	 *
	 * @param dateStr 时间字符串
	 * @param df      时间字符串格式，如：yyyy-MM-dd HH:mm:ss
	 * @return Date   返回日期
	 */
	public static Date toDate(String dateStr, SimpleDateFormat df) {
		if (StringUtils.isBlank(dateStr) || df == null) {
			return null;
		}
		try {
			return df.parse(dateStr);
		} catch (Exception e) {
			logger.error(dateStr + df.toString() + ", {}", e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 时间字符串转化成 Calendar
	 *
	 * @param dateStr 时间字符串
	 * @param df      时间字符串格式，如：yyyy-MM-dd HH:mm:ss
	 * @return Calendar  返回日期
	 */
	public static Calendar toCalendar(String dateStr, SimpleDateFormat df) {
		Date temp = toDate(dateStr, df);
		Calendar cal = Calendar.getInstance();
		cal.setTime(temp);
		return cal;
	}

	/**
	 * 时间转化成字符串
	 *
	 * @param date 时间，null为当前时间
	 * @param df   时间字符串格式，如：yyyy-MM-dd HH:mm:ss
	 * @return String 返回日期字符串
	 */
	@Deprecated
	public static String format(Date date, SimpleDateFormat df) {
		date = date == null ? new Date() : date;
		return df.format(date);
	}

	/**
	 * 时间计算
	 *
	 * @param date   时间，null为当前时间
	 * @param field  对哪个属性进行计算；1：年；2：月；3：日；4：小时；5：分钟
	 * @param amount 要增加的值
	 * @return Date  返回日期
	 */
	public static Date addTime(Date date, int field, int amount) {
		date = date == null ? new Date() : date;
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		if (field == 1) {
			cal.add(Calendar.YEAR, amount);
		} else if (field == 2) {
			cal.add(Calendar.MONTH, amount);
		} else if (field == 3) {
			cal.add(Calendar.DATE, amount);
		} else if (field == 4) {
			cal.add(Calendar.HOUR, amount);
		} else if (field == 5) {
			cal.add(Calendar.MINUTE, amount);
		}
		return cal.getTime();
	}

	/**
	 * 设置时间计算，值为-1，该项不修改不设值
	 * <p>
	 * set(YEAR, year);
	 * set(MONTH, month);
	 * set(DATE, date);
	 * set(HOUR_OF_DAY, hourOfDay);
	 * set(MINUTE, minute);
	 * set(SECOND, second);
	 *
	 * @param date        时间，null为当前时间
	 * @param year        年
	 * @param month       月
	 * @param day         日
	 * @param hourOfDay   小时
	 * @param minute      分
	 * @param second      秒
	 * @param millisecond 毫秒
	 * @return Date  返回日期
	 */
	public static Date setTime(Date date, int year, int month, int day, int hourOfDay, int minute, int second, int millisecond) {
		date = date == null ? new Date() : date;
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		if (year != -1) {
			cal.set(Calendar.YEAR, year);
		}
		if (month != -1) {
			cal.set(Calendar.MONTH, month);
		}
		if (day != -1) {
			cal.set(Calendar.DATE, day);
		}
		if (hourOfDay != -1) {
			cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
		}
		if (minute != -1) {
			cal.set(Calendar.MINUTE, minute);
		}
		if (second != -1) {
			cal.set(Calendar.SECOND, second);
		}
		if (millisecond != -1) {
			cal.set(Calendar.MILLISECOND, millisecond);
		}
		return cal.getTime();
	}

	/**
	 * 两个时间之间的天数
	 *
	 * @param startDate 起始时间
	 * @param endDate   结束时间
	 * @return long   两个时间间的天数
	 */
	public static long daysBetweenTwoDate(Date startDate, Date endDate) {
		return (endDate.getTime() - startDate.getTime()) / day_ms;
	}

	/**
	 * 两个时间之间的小时数
	 *
	 * @param startDate 起始时间
	 * @param endDate   结束时间
	 * @return long   两个时间间的天数
	 */
	public static long hoursBetweenTwoDate(Date startDate, Date endDate) {
		return (endDate.getTime() - startDate.getTime()) % day_ms / hour_ms;
	}

	/**
	 * 获得指定日期是一周的第几天，星期一是第一天，星期二是第二天......星期天是第七天
	 */
	public static int weekday(Date date) {
		Calendar cd = Calendar.getInstance();
		date = date == null ? new Date() : date;
		cd.setTime(date);
		int i = cd.get(Calendar.DAY_OF_WEEK);
		if (i > 1) {
			return i - 1;
		}
		return 7;
	}

	/**
	 * 获取指定年月份的第一天和最后一天
	 *
	 * @param month 格式   yyyy-MM 日期格式
	 */
	public static Map<String, String> monthForFirstDayAndLastDay(Date month) {
		if (month == null) {
			return null;
		}
		Map<String, String> result = new HashMap<>();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(month);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		result.put("firstDay", DateUtil.format(calendar.getTime(), DateUtil.DF_YMD));
		calendar.roll(Calendar.DAY_OF_MONTH, -1);
		result.put("lastDay", DateUtil.format(calendar.getTime(), DateUtil.DF_YMD));
		return result;
	}

	/**
	 * 获取指定年月份的第一天
	 *
	 * @param month 格式   yyyy-MM-dd 日期格式
	 */
	public static String monthFirstDay(Date month) {
		if (month == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(month);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return DateUtil.format(calendar.getTime(), DateUtil.DF_YMD);
	}

	/**
	 * 获取指定年月份的最后一天
	 *
	 * @param month 格式   yyyy-MM-dd 日期格式
	 */
	public static String monthLastDay(Date month) {
		if (month == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(month);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return DateUtil.format(calendar.getTime(), DateUtil.DF_YMD);
	}

	/**
	 * 根据开始时间和结束时间返回时间段内的时间集合
	 *
	 * @param beginDate 开始日期
	 * @param endDate   结束日期
	 * @return 时间集合
	 */
	public static List<String> getDatesBetweenTwoDate(Date beginDate, Date endDate) {
		List<Date> lDate = new ArrayList<>();
		lDate.add(beginDate);//把开始时间加入集合
		Calendar cal = Calendar.getInstance();
		//使用给定的 Date 设置此 Calendar 的时间
		cal.setTime(beginDate);
		while (true) {
			//根据日历的规则，为给定的日历字段添加或减去指定的时间量
			cal.add(Calendar.DAY_OF_MONTH, 1);
			// 测试此日期是否在指定日期之后
			if (endDate.after(cal.getTime())) {
				lDate.add(cal.getTime());
			} else {
				break;
			}
		}
		lDate.add(endDate);//把结束时间加入集合
		List<String> times = new ArrayList<>();
		for (Date date : lDate) {
			times.add(DateUtil.format(date, DateUtil.DF_YMD));
		}
		return times;
	}

	/**
	 * 获取本周一和本周日的日期
	 */
	public static Map<String, String> getWeekFirthDayAndLastDay() {
		Map<String, String> result = new HashMap<>();
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); //获取本周一的日期
		result.put("first", DateUtil.format(cal.getTime(), DateUtil.DF_YMD));
		cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
		cal.add(Calendar.WEEK_OF_YEAR, 1);              //获取本周日的日期
		result.put("last", DateUtil.format(cal.getTime(), DateUtil.DF_YMD));
		return result;
	}


	/**
	 * 将日期转换成周几（如果是本周不加“本”字）
	 *
	 * @param date 日期
	 * @return 周几
	 */
	public static String day2WeekDay(Date date) {
		Calendar cd = Calendar.getInstance();
		date = date == null ? new Date() : date;
		cd.setTime(date);
		int i = cd.get(Calendar.DAY_OF_WEEK);
		if (i > 0) {
			i = i - 1;
		}
		String week = null;
		switch (i) {
			case 1:
				week = "周一";
				break;
			case 2:
				week = "周二";
				break;
			case 3:
				week = "周三";
				break;
			case 4:
				week = "周四";
				break;
			case 5:
				week = "周五";
				break;
			case 6:
				week = "周六";
				break;
			case 0:
				week = "周日";
				break;
		}
		return week;
	}

	/**
	 * 时间格式化
	 *
	 * @param date       日期
	 * @param df         样式
	 * @param isInterDay 是否跨天， true:是，false:否
	 * @return 格式化后的时间
	 */
	public static String format(Date date, DateTimeFormatter df, boolean isInterDay) {
		date = date == null ? new Date() : date;
		if (isInterDay) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			if (calendar.get(Calendar.HOUR_OF_DAY) < 10) {
				date = addTime(date, 3, -1);
			}
		}
		return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().format(df);
	}

	/**
	 * 时间格式化
	 *
	 * @param date 日期
	 * @param df   样式
	 * @return
	 */
	public static String format(Date date, DateTimeFormatter df) {
		date = date == null ? new Date() : date;
		return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().format(df);
	}


	/**
	 * 以下方法与常量是线程安全的，请尽量用下列方法与常量
	 */

	public final static DateTimeFormatter DTF_MMM_EN = DateTimeFormatter.ofPattern("MMM", Locale.US);
	public final static DateTimeFormatter DTF_YMD_EN = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.US);
	public final static DateTimeFormatter DTF_YMA_EN = DateTimeFormatter.ofPattern("HH:mm a", Locale.US);
	public final static DateTimeFormatter DTF_HMA_12_EN = DateTimeFormatter.ofPattern("hh:mm a", Locale.US);
	public final static DateTimeFormatter DTF_YMDHM_24_EN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm", Locale.US);
	public final static DateTimeFormatter DTF_YMDHMS_24_EN = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.US);
	public final static DateTimeFormatter DTF_HMAMD_24_EN = DateTimeFormatter.ofPattern("hh:mm a MM/dd", Locale.US);
	public final static DateTimeFormatter DTF_DMMM_24_EN = DateTimeFormatter.ofPattern("d MMM", Locale.US);
	public final static DateTimeFormatter DTF_DMMMY_24_EN = DateTimeFormatter.ofPattern("d MMM yyyy", Locale.US);
	public final static DateTimeFormatter DTF_EDMMMHMA_24_EN = DateTimeFormatter.ofPattern("E, d MMM, hh:mm a", Locale.US);// Fri, 30 Mar, 11:05 AM
	public final static DateTimeFormatter DTF_EDMMMYHMA_24_EN = DateTimeFormatter.ofPattern("E, d MMM yyyy, hh:mm a", Locale.US);// Fri, 30 Mar 2017, 11:05 AM
	public final static DateTimeFormatter DTF_DMMMYHMA_24_EN = DateTimeFormatter.ofPattern("d MMM yyyy, hh:mm a", Locale.US);// 30 Mar 2017, 11:05 AM

	public final static DateTimeFormatter DTF_YMD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
	public final static DateTimeFormatter DTF_YMD2 = DateTimeFormatter.ofPattern("yyyy/MM/dd");
	public final static DateTimeFormatter DTF_Y = DateTimeFormatter.ofPattern("yyyy");
	public final static DateTimeFormatter DTF_M = DateTimeFormatter.ofPattern("M");
	public final static DateTimeFormatter DTF_DD = DateTimeFormatter.ofPattern("dd");
	public final static DateTimeFormatter DTF_YMD_DOT = DateTimeFormatter.ofPattern("yyyy.MM.dd");
	public final static DateTimeFormatter DTF_HM = DateTimeFormatter.ofPattern("HH:mm");
	public final static DateTimeFormatter DTF_HMS = DateTimeFormatter.ofPattern("HH:mm:ss");
	public final static DateTimeFormatter DTF_MD = DateTimeFormatter.ofPattern("MM.dd");
	public final static DateTimeFormatter DTF_YMDHM_24 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
	public final static DateTimeFormatter DTF_YMDHM_DOT_24 = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm");
	public final static DateTimeFormatter DTF_HHMM_ZH = DateTimeFormatter.ofPattern("H时mm分");
	public final static DateTimeFormatter DTF_MMDDHHMM_ZH = DateTimeFormatter.ofPattern("M月d日H时mm分");
	public final static DateTimeFormatter DTF_YM_ZH = DateTimeFormatter.ofPattern("MM月dd日");
	public final static DateTimeFormatter DTF_MMDDHHMM2_ZH = DateTimeFormatter.ofPattern("MM月dd日 HH:mm");
	public final static DateTimeFormatter DTF_YYYYMMDD_ZH = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
	public final static DateTimeFormatter DTF_MMDD_ZH = DateTimeFormatter.ofPattern("MM月dd日");
	public final static DateTimeFormatter DTF_YYYYMMDDHHMM_ZH = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm");
	public final static DateTimeFormatter DTF_MDHM_24 = DateTimeFormatter.ofPattern("MM-dd HH:mm");
	public final static DateTimeFormatter DTF_YMDHMSS_24 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	public final static DateTimeFormatter DTF_YMD_FULL = DateTimeFormatter.ofPattern("yyyyMMdd");
	public final static DateTimeFormatter DTF_YMDHMSS = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
	public final static DateTimeFormatter DTF_MDYHDS = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
	public final static DateTimeFormatter DTF_MDHM_DOT = DateTimeFormatter.ofPattern("MM.dd HH:mm");
	public final static DateTimeFormatter DTF_YMDH_24 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");

	/**
	 * DATE_2099_12_31 2099年12月31日 23时59分59秒
	 */
	public final static Date DATE_2099_12_31 = toDateTime2("2099-12-31 23:59:59", DateUtil.DTF_YMDHMSS_24);

	/**
	 * 转换成日期    注：不是日期带时间，是日期
	 *
	 * @param dateStr 日期
	 * @param df      日期样式
	 * @return 当前日期
	 */
	public static LocalDate toDate(String dateStr, DateTimeFormatter df) {
		if (StringUtils.isBlank(dateStr) || df == null) {
			return null;
		}
		try {
			return LocalDate.parse(dateStr, df);
		} catch (Exception e) {
			logger.error(dateStr + df.toString() + ", {}", e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 转换成日期 注意区分toDateTime2
	 *
	 * @param dateStr 日期
	 * @param df      日期格式
	 * @return 日期
	 */
	public static Date toDate2(String dateStr, DateTimeFormatter df) {
		try {
			LocalDate localDate = toDate(dateStr, df);
			if (localDate != null) {
				return localDate2Date(localDate);
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error(dateStr + df.toString() + ", {}", e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 转换成时间  注：这个是包含日期与时间的
	 *
	 * @param dateStr 日期+时间
	 * @param df      日期时间样式
	 * @return 当前时间
	 */
	public static LocalDateTime toDateTime(String dateStr, DateTimeFormatter df) {
		if (StringUtils.isBlank(dateStr) || df == null) {
			return null;
		}
		try {
			return LocalDateTime.parse(dateStr, df);
		} catch (Exception e) {
			logger.error(dateStr + df.toString() + ", {}", e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 转换成时间 注：这个是包含日期与时间的;返回date
	 *
	 * @param dateStr 日期+时间
	 * @param df      日期时间样式
	 * @return 返回date，已经将LocalDateTime转化为Date
	 */
	public static Date toDateTime2(String dateStr, DateTimeFormatter df) {
		try {
			LocalDateTime localDateTime = toDateTime(dateStr, df);
			if (localDateTime != null) {
				return localDateTime2Date(localDateTime);
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error(dateStr + df.toString() + ", {}", e.getMessage(), e);
			return null;
		}
	}

	/**
	 * 计算两个日期之间的天数(按日期来计算)
	 *
	 * @param begin 开始日期
	 * @param end   结束日期
	 * @return 两个日期之间的天数
	 */
	public static long between(Date begin, Date end) {
		LocalDate beginDate = date2LocalDate(begin);
		LocalDate endDate = date2LocalDate(end);
		return endDate.toEpochDay() - beginDate.toEpochDay();
	}

	/**
	 * 把日期转换成本地日期（线程安全）
	 *
	 * @param date 日期
	 * @return 本地日期
	 */
	public static LocalDate date2LocalDate(Date date) {
		return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalDate();
	}

	/**
	 * 日期转换(线程安全)
	 *
	 * @param date 日期
	 */
	public static LocalDateTime date2LocalDateTime(Date date) {
		return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
	}

	/**
	 * 把本地日期转换成日期（线程安全）
	 *
	 * @param localDateTime 日期 + 时间
	 */
	public static Date localDateTime2Date(LocalDateTime localDateTime) {
		return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * 把本地日期转换成日期（线程安全）
	 *
	 * @param localDate 日期
	 */
	public static Date localDate2Date(LocalDate localDate) {
		return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * 获取日期的年、月、日等
	 *
	 * @param date  指定日期，为空时为当前日期
	 * @param field Calendar.YEAR、Calendar.MONTH、Calendar.DATE、Calendar.
	 *              HOUR_OF_DAY、Calendar.MINUTE
	 */
	public static int get(Date date, int field) {
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}
		return calendar.get(field);
	}

	/**
	 * 判断指定日期对比现在是否在指定范围，如：是否在今天、昨天
	 *
	 * @param date 指定日期
	 * @param type 0=今天、1=昨天、2=前天、10=今年
	 */
	public static boolean checkDateByType(Date date, int type) {
		boolean result = false;
		if (date == null) {
			return false;
		}
		long time = date.getTime();
		// 今天开始时间毫秒
		long todayStartTime = toDateTime2(format(new Date(), DTF_YMD) + " 00:00:00", DTF_YMDHMSS_24).getTime();
		switch (type) {
			case 0: { // 今天
				if (time >= todayStartTime && time < todayStartTime + day_ms) {
					result = true;
				}
				break;
			}
			case 1: { // 昨天
				if (time < todayStartTime && time >= todayStartTime - day_ms) {
					result = true;
				}
				break;
			}
			case 2: { // 前天
				if (time < todayStartTime - day_ms && time >= todayStartTime - day_ms * 2) {
					result = true;
				}
				break;
			}
			case 10: { // 今年
				int year = get(date, Calendar.YEAR);
				int currentYear = get(null, Calendar.YEAR);
				if (year == currentYear) {
					result = true;
				}
				break;
			}
			default:
				break;
		}
		return result;
	}

	/**
	 * 获取当前时间戳，秒
	 *
	 * @return 结果
	 */
	public static long getCurrentSecond() {
		return System.currentTimeMillis() / 1000;
	}

	/**
	 * 获取今天开始时间毫秒
	 *
	 * @return 结果
	 */
	public static long getTodayStartTime() {
		// 今天开始时间毫秒
		return toDateTime2(format(new Date(), DTF_YMD) + " 00:00:00", DTF_YMDHMSS_24).getTime();
	}

	/**
	 * 获取今天结束时间毫秒
	 *
	 * @return 结果
	 */
	public static long getTodayEndTime() {
		// 今天结束时间毫秒
		return toDateTime2(format(new Date(), DTF_YMD) + " 23:59:59", DTF_YMDHMSS_24).getTime();
	}

}
